﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zmotion406.Models;
using cszmcaux;
using static cszmcaux.Zmcaux;
using System.Reflection.Metadata;
using System.Threading;

namespace Zmotion406.Service
{
    public class AxisService
    {
        /// <summary>
        /// 单轴 相对/绝对 运动
        /// </summary>
        /// <param name="axis">轴参数</param>
        /// <param name="AxleNumber">轴号</param>
        /// <param name="distance">距离</param>
        /// <returns></returns>
        public static int RobotAxisContinuousMive(AxisModel axis, int AxleNumber,int distance)
        {
            if (IsConnected())
            {
                int res = SetAxisConfig(axis, AxleNumber);
                if (res == 0) { 
                    if (axis.motorPattern == 1)
                    {
                        // 相对
                        return ZAux_Direct_Single_Move(ConfigModel.Handle, AxleNumber, distance);
                    }
                    else if (axis.motorPattern == 2)
                    {
                        // 绝对
                        return ZAux_Direct_Single_MoveAbs(ConfigModel.Handle, AxleNumber, distance);
                    }
                }
            }
            return 9999; // 错误

        }
        /// <summary>
        /// 监听单轴是否运动完成
        /// </summary>
        /// <param name="action">完成界面变更委托</param>
        /// <param name="AxleNumber">轴号</param>
        public static void IsOVerMove(Action<int> action,int AxleNumber)
        {
            Task.Run(() =>
            {
                int isIdle = 0;
                while (true)
                {
                    Thread.Sleep(100);
                    int res = ZAux_Direct_GetIfIdle(ConfigModel.Handle, AxleNumber, ref isIdle);
                    if (res == 0)
                    {
                        if(isIdle == -1)
                        {
                            action(isIdle);
                            break;
                        }
                    }
                }

            });
        }
        /// <summary>
        /// 单轴连续 运动启动
        /// </summary>
        /// <param name="axis">运动参数</param>
        /// <param name="AxleNumber">轴号</param>
        /// <param name="idir">方向</param>
        /// <returns></returns>
        public static int RobotAxisClickMove(AxisModel axis,int AxleNumber,int idir)
        {
            if (!IsConnected())
            {
                return 9999; // 未连接
            }
            int res = SetAxisConfig(axis, AxleNumber);
            if(res == 0)
            {
                res = ZAux_Direct_Single_Vmove(ConfigModel.Handle, AxleNumber, idir);
                return res;
            }
            return 9999;
        }
        /// <summary>
        /// 取消运动
        /// </summary>
        /// <param name="AxleNumber"></param>
        /// <returns></returns>
        public static int CloseMove(int AxleNumber)
        {
            if (IsConnected())
            {
                return ZAux_Direct_Single_Cancel(ConfigModel.Handle, AxleNumber,2); // 取消点动运动
            }
            return 9999;
        }
        /// <summary>
        /// 设置轴参数
        /// </summary>
        /// <param name="axis">参数值对象</param>
        /// <param name="AxleNumber">轴编号</param>
        /// <returns>设置状态</returns>
        public static int SetAxisConfig(AxisModel axis,int AxleNumber)
        {
            if (IsConnected()) 
            {
                int res;
                res = ZAux_Direct_SetAtype(ConfigModel.Handle, AxleNumber, 65); // 设置轴类型
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetUnits(ConfigModel.Handle, AxleNumber, axis.Pulse); // 设置脉冲当量
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetAccel(ConfigModel.Handle,AxleNumber,axis.AcceleratedSpeed); // 设置加速度
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetDecel(ConfigModel.Handle, AxleNumber, axis.Deceleration); // 设置减速度
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetSpeed(ConfigModel.Handle, AxleNumber, axis.RunningSpeed); // 设置运行速度
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetLspeed(ConfigModel.Handle, AxleNumber, axis.StartSpeed); // 设置起始速度
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetSramp(ConfigModel.Handle, AxleNumber, axis.Curve); // 设置S曲线
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetFsLimit(ConfigModel.Handle, AxleNumber, axis.PositiveLimitPosition); // 设置正限位
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetRsLimit(ConfigModel.Handle, AxleNumber, -Math.Abs(axis.PositiveLimitPosition)); // 设置正限位
                if (!CaptureError(res)) return res;

                return 0; // 成功
            }
            return 9999; // 未连接

        }
        /// <summary>
        /// 判断设置轴参数是否成功
        /// </summary>
        /// <param name="res">返回true为正确配置</param>
        /// <returns></returns>
        public static bool CaptureError(int res)
        {
            if (res != 0)
            {
                Console.WriteLine($"Error: 轴参数配置错误，错误码：{res}");
                return false; // 错误
            }
            return true; // 成功
        }
            /// <summary>
            /// 获取连接状态
            /// </summary>
            /// <returns></returns>
        public static bool IsConnected()
        {
            if (ConfigModel.Handle == IntPtr.Zero)
            {
                Console.WriteLine("Error: 控制器未连接或句柄无效。");
                //MessageBox.Show("控制器未连接或句柄无效，请检查连接状态。");
                return false; // 未连接
            }
            return true; // 已连接
        }
        /// <summary>
        /// 保存归零位置
        /// </summary>
        /// <param name="axis"></param>
        /// <returns></returns>
        public static int SaveOriginMark(int axis)
        {
            if (IsConnected())
            {
                int res = ZAux_Direct_Single_Datum(ConfigModel.Handle, axis, 2);
                if(res == 0)
                {
                    ConfigModel.AxisMark[axis] = new TempAxis()
                    {
                        State = true,
                        NewCircle = 0
                    };
                }
                res = ZAux_Direct_SetDpos(ConfigModel.Handle, axis, 0);  // 规划轴清零
                if (!CaptureError(res)) return res;
                res = ZAux_Direct_SetMpos(ConfigModel.Handle, axis, 0);  // 反馈位置清零
                if (!CaptureError(res)) return res;
                // 是否应该重新执行运动？
                return res;
            }
            return 9999;
        }
        /// <summary>
        /// 计算电机圈数
        /// </summary>
        /// <param name="AxisNumber"></param>
        /// <param name="Circle"></param>
        /// <returns></returns>
        public static int Inquiry_Mark(int AxisNumber,out float Circle)
        {
            float pulse = 0;
            int resolution = 10000 * 4;
            int res = ZAux_Direct_GetDpos(ConfigModel.Handle, AxisNumber,ref pulse);
            if(res == 0)
            {
                Circle = pulse / resolution;
                ConfigModel.AxisMark[AxisNumber].NewCircle = Circle;
                return 0;
            }
            Circle = 0;
            return 9999;
        }
        /// <summary>
        /// 检查是否触发限位警报
        /// </summary>
        /// <param name="AxisNumber"></param>
        /// <returns></returns>
        public static int AxisAlarm(int AxisNumber)
        {
                float IDLE = 0;
                int AxisStatus = 0;
                int Count = 0;
                while (true)
                {
                    Thread.Sleep(100);
                    Count++;
                    ZAux_Direct_GetParam(ConfigModel.Handle, "IDLE", AxisNumber, ref IDLE);
                    if (IDLE < 0) break;
                    if (Count > 50) break;
                }
                ZAux_Direct_GetAxisStatus(ConfigModel.Handle, AxisNumber, ref AxisStatus);
                return AxisStatus;
        }

    }
}
